﻿/*******************************************************************************
 * AAEngine
 * Copyright (c) 2010 Mike Jarosch
 *
 * Original source PushButton Engine:
 * Copyright (C) 2009 PushButton Labs, LLC
 * For more information see http://www.pushbuttonengine.com
 *
 * This file is licensed under the terms of the MIT license, which is included
 * in the "MIT License.txt" file at the root directory of this SDK.
 ******************************************************************************/

using System;
using AAEngine.Engine.Core;
using AAEngine.Engine.Entities;

namespace AAEngine.Engine.Components
{
    /// <summary>
    /// Base class for components which want to use think notifications.
    /// </summary>
    /// <remarks>
    /// "Think notifications" allow a component to specify a time and
    /// callback function which should be called back at that time. In this
    /// way you can easily build complex behavior (by changing which callback
    /// you pass) which is also efficient (because it is only called when
    /// needed, not every tick/frame). It is also light on the GC because
    /// no allocations are required beyond the initial allocation of the
    /// ThinkingComponent.
    /// </remarks>
    public class ThinkingComponent : EntityComponent, IQueuedObject
    {
        double _nextThinkTime;
        Action _nextThinkCallback;

        /// <summary>
        /// Schedule the next time this component should think.
        /// </summary>
        /// <param name="nextCallback">Function to be executed.</param>
        /// <param name="timeUntillNextThink">Time in ms from now at which to execute the function (approximately).</param>
        public void Think(Action nextCallback, double timeUntillNextThink)
        {
            _nextThinkTime = AAGame.ProcessManager.VirtualTime + timeUntillNextThink;
            _nextThinkCallback = nextCallback;

            AAGame.ProcessManager.QueueObject(this);
        }

        public override void OnRemove()
        {
            base.OnRemove();

            _nextThinkCallback = null;
        }

        public float NextThinkTime
        {
            get { return (float)_nextThinkTime; }
        }

        public Action NextThinkCallback
        {
            get { return _nextThinkCallback; }
        }

        public int Priority
        {
            get
            {
                return (int)-_nextThinkTime;
            }
            set
            {
                throw new NotImplementedException();
            }
        }
    }
}
